package com.wtpaint.lib.zhttp;

import com.wtpaint.lib.zhttp.chain.Interceptor;
import com.wtpaint.lib.zhttp.chain.InterceptorChain;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class Call {
    private Request request;
    private HttpClient client;
    private boolean executed;
    private boolean canceled;

    public Call(Request request, HttpClient client) {
        this.request = request;
        this.client = client;
    }

    public boolean isCanceled() {
        return canceled;
    }

    public HttpClient client() {
        return client;
    }

    public void cancel() {
        canceled = true;
    }

    public void enqueue(Callback callback) {
        synchronized (this) {
            if (executed) {
                throw new IllegalStateException("call has been executed");
            }
            executed = true;
        }
        client.dispatcher().enqueue(new AsyncCall(callback));
    }

    public Response getResponse() throws IOException {
        List<Interceptor> interceptors = new ArrayList<>();
        InterceptorChain chain = new InterceptorChain(interceptors, 0, this);
        return chain.process();
    }

    class AsyncCall implements Runnable {

        private Callback callback;

        public AsyncCall(Callback callback) {
            this.callback = callback;
        }

        @Override
        public void run() {
            boolean signalledCallbacked = false;
            try {
                Response response = getResponse();
                signalledCallbacked = true;
                if (isCanceled()) {
                    callback.onFailure(Call.this, new IOException(""));
                } else {
                    callback.onSuccess(Call.this, response);
                }
            } catch (Exception e) {
                if (!signalledCallbacked) {
                    callback.onFailure(Call.this, e);
                }
            } finally {
                //执行完后的任务从调度器中移除
                client().dispatcher().finished(this);
            }
        }

        public String host() {
            return request.url().getHost();
        }
    }
}
